/*
* Copyright (C) Microsoft. All rights reserved.  
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not 
* use this file except in compliance with the License.  You may obtain a copy 
* of the License at http://www.apache.org/licenses/LICENSE-2.0  
* 
* THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED 
* WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, 
* MERCHANTABLITY OR NON-INFRINGEMENT. 
*
* See the Apache License, Version 2.0 for specific language governing 
* permissions and limitations under the License.
*
*/
#include "pch.h"
#include <journal/models/ink_stroke_model_factory.h>
#include <journal/models/db/ink_stroke_table.h>
#include <journal/models/ink_stroke_model.h>

using namespace journal::model;

b::uint32 ink_stroke_model_factory::_typeToken = 0;

ink_stroke_model_factory::ink_stroke_model_factory() :
    _nextId(0)
{
    if (_typeToken == 0)
    {
        _typeToken = constants::undoRedoService()->generateTargetTypeToken();

        constants::memoryTrackingService()->registerType(_typeToken, L"ink stroke model", true);

        DEBUG_CONSOLE_TRACE_TAG(TRACE_TAG_GENERIC_MODEL,
            boost::wformat(L"ink_stroke_model_factory::ink_stroke_model_factory() : type token = %i") %
            _typeToken
            );
    }
}

std::shared_ptr<iink_stroke_model_factory> ink_stroke_model_factory::create()
{
    static std::shared_ptr<iink_stroke_model_factory> returnValue = std::make_shared<ink_stroke_model_factory>();
    return returnValue;
}

std::shared_ptr<iink_stroke_model> ink_stroke_model_factory::createInkStroke(
    const std::shared_ptr<iink_surface_model>& parent)
{
    return journal::model::createInkStroke(_typeToken, parent, _nextId++);
}

std::shared_ptr<iink_stroke_model> ink_stroke_model_factory::recreateInkStroke(
    const std::shared_ptr<iink_surface_model>& parent,
    const b::uint32& strokeId)
{
    return journal::model::createInkStroke(_typeToken, parent, strokeId);
}

std::shared_ptr<iink_stroke_model> ink_stroke_model_factory::recreateInkStroke(
        const std::shared_ptr<iink_surface_model>& parent,
        const s::binary_blob& inBlob,
        b::uint32& offset
        )
{
    std::shared_ptr<iink_stroke_model> inkStroke = journal::model::createInkStroke(_typeToken, parent, 0);

    // unpack blob into the new stroke...
    std::shared_ptr<iinternal_model_blob> strokeBlob = std::dynamic_pointer_cast<iinternal_model_blob>(inkStroke);
    strokeBlob->unpackFromBlob(inBlob, offset);

    // don't forget to register the unpacked id...
    b::uint32 id = inkStroke->storageId();
    if (_nextId <= id)
    {
        _nextId = id + 1;
    }

    return inkStroke;
}

std::shared_ptr<iink_stroke_model_factory> journal::model::createInkStrokeModelFactory()
{
    return ink_stroke_model_factory::create();
}
